#ifndef SOLVER_H
#define SOLVER_H

#include <iostream>
#include <QObject>

#include "defines/methods.h"
#include "matrix.h"
#include "fabric.h"
#include "object.h"


class Solver : public QObject
{
    Q_OBJECT

	public:

		Solver();

		Solver(std::vector<Fabric *> *, std::vector<Object *> *, unsigned int, double, double, bool, double, double, bool, int, double, double, double, Vector3D);

		~Solver();

		IntegrationMethod *getIntegrationMethod(){return method;};

		virtual void calculate(bool) = 0;

		void restart();

		//Vector3D calculateRepulsiveForce (const Vector3D&, const Vector3D&, double, double);

		void setDampingFactor(double _d){collisionDampingFactor = _d;};
        void setDistanceError(double _d){collisionDistanceError = _d;};
        void setActiveCollision(bool _b){testCollision = _b;};

    signals:
        void pause(bool);

    protected:
        bool firstIteration; //tells if we are in the first calculation

        unsigned int totalFramesTime; //in milliseconds
        unsigned int totalMethodTime; //in milliseconds

        unsigned int totalFrames;

        unsigned int recordFrameInTotal;

        unsigned int recordFrameIn;

        IntegrationMethod *method; //integration method

        std::vector<Fabric *> *fabrics; //vector of fabrics

        std::vector<Object *> *objects; //a list of objects

		std::vector<State> getStates(); //return the vectors of States

        //used in collision;
        bool testCollision;
        double collisionDampingFactor; //used to attenuate the particle when its returning
        double collisionDistanceError; //used to mask taht the fabric is in the object


		void changeSettings(unsigned int, double, double, bool, int, double, double, double, Vector3D); //change the methods
};

#endif
